package aquerius

/**
 * @author: Yardena
 * @date: Aug 15, 2009 11:45:43 PM
 */

trait Expressions {

  type ExpressionType[-X,+Y]  <: Expression[X,Y]
  type BoolExpressionType[-X] <: ExpressionType[X,Boolean] with BoolExpression[X]
  type IntExpressionType[-X]  <: ExpressionType[X,Int]     with IntExpression[X]
  type StrExpressionType[-X]  <: ExpressionType[X,String]  with StrExpression[X]

  trait Expression[-F,+T] {
    type Source = F
    def is[S<:F]    (other: ExpressionType[S,_]) : BoolExpressionType[S]
    def isNot[S<:F] (other: ExpressionType[S,_]) : BoolExpressionType[S]
  }

  trait BoolExpression[-F] extends Expression[F,Boolean] {
    def and[S<:F] (other:  BoolExpressionType[S]): BoolExpressionType[S]
    def or[S<:F]  (other:  BoolExpressionType[S]): BoolExpressionType[S]
    def not: BoolExpressionType[_ >: F]
    def unary_! = not
  }
  final def not[F](expr: BoolExpression[F]) = expr not

  trait IntExpression[-F] extends Expression[F,Int] {
    def +[S<:F] (other: IntExpressionType[S]): IntExpressionType[S]
    def -[S<:F] (other: IntExpressionType[S]): IntExpressionType[S]
    def >[S<:F] (other: IntExpressionType[S]): BoolExpressionType[S]
    def <[S<:F] (other: IntExpressionType[S]): BoolExpressionType[S]
  }

  trait StrExpression[-F] extends Expression[F,String] {
    def startsWith[S<:F] (str : StrExpressionType[S]): BoolExpressionType[S]
    def contains[S<:F]   (str : StrExpressionType[S]): BoolExpressionType[S]
  }

  implicit def const(b: Boolean): BoolExpressionType[Any]
  implicit def const(i: Int):     IntExpressionType[Any]
  implicit def const(s: String):  StrExpressionType[Any]

}